home *** CD-ROM | disk | FTP | other *** search
/ Graphics Plus / Graphics Plus.iso / general / raytrace / radiance / simplerd.lha / simplerad / FinalFTP / Light / polyf.c < prev    next >
Encoding:
C/C++ Source or Header  |  1992-05-17  |  32.2 KB  |  1,007 lines

  1. /**********************************************************************/
  2. /* poly.c                                                             */
  3. /*                                                                    */
  4. /* Read in polygons from and input file of format:                    */
  5. /*                                                                    */
  6. /* Number objects <number-objects>                                    */
  7. /* Object <object-id> (object-type) {                                 */
  8. /*     OWMatrix <matrix-id> { (matrix) }                              */
  9. /*     prop <property-id> { E{ vec } p{ vec } Kd{ val } Ks{ val }     */
  10. /*     NumMeshes <number-of-meshes>                                   */
  11. /*     (possible-mesh)                                                */
  12. /*                                                                    */
  13. /*  OWMatrix identifies an object to world matrix,                    */
  14. /*  prop identifies an object property, E is the emittance,           */
  15. /*  p is the reflectance, Kd = diffuse component, and Ks the specular */
  16. /*                                                                    */
  17. /* where:                                                             */
  18. /*  object-type = mesh, cube, cone, cylinder, or sphere               */
  19. /*  matrix = { vec } { vec } { vec } { vec }                          */
  20. /*  vec = val val val                                                 */
  21. /*  val = floating point value                                        */
  22. /*  possible-mesh = if (object-type == mesh) { read-mesh-in-place }   */
  23. /*                  else { mesh-read-from-file }                      */
  24. /*  mesh = Mesh <mesh-id> <number-polygons> {                         */
  25. /*            Patch vert<vertex#> <num-vertices> { vertices }         */
  26. /*            Patch norm<norm#>   <num-normals>  { normals }          */
  27. /*  vertices = { vec } { vec } ...                                    */
  28. /*  normals  = { vec } { vec } ...                                    */
  29. /*                                                                    */
  30. /**********************************************************************/
  31. #include <stdio.h>
  32. #include <stdlib.h>
  33. #include <string.h>
  34. #include <math.h>
  35. #include "misc.h"
  36. #include "geo.h"
  37. #include "struct.h"
  38. #include "io.h"
  39. #include "poly.h"
  40. #include "rad.h"
  41. #include "adj.h"
  42. #include "bvol.h"
  43. #include "ff.h"
  44. #include "rtime.h"
  45.  
  46. #define ENLARGE_BOX   (0.000)         /* Amount to enlarge obj BV by */
  47. #define ENLARGE_WORLD (0.6)           /* Amount to enlarge world BV by */
  48.  
  49. extern Time_Stats tstats;
  50. extern double MIN_ELEMENT_PERC;
  51. extern HBBox Scene_BVH;
  52. extern Vertex_list *vlist;
  53. extern unsigned long vlist_size;
  54. extern Vertex_tree *vtree;
  55. extern unsigned long vtree_size;
  56. extern FF_OptionType FF_Options;
  57. extern BoundingBoxType BoxCone();
  58. extern BoundingBoxType BoxCube();
  59. extern BoundingBoxType BoxCylinder();
  60. extern BoundingBoxType BoxSphere();
  61. extern void SetOptions();
  62. extern void LogStats();
  63. extern void LogRlog();
  64. extern void Create_Initial_ReceiverList();
  65.  
  66. #ifdef IRIS4D
  67. extern void InitRad();
  68. extern void DoRad();
  69. extern void CleanUpRad();
  70. #endif /* IRIS4D */
  71.  
  72. /**********************************************************************/
  73. /* Structures for reading scene */
  74. /**********************************************************************/
  75. char *tmp = "                   ";
  76. char *tmp2 = "                  ";
  77. float tmpf[9];             /* For floating pt reading only ! */
  78. int premesh = 0;
  79.  
  80. RadParams ReadLog;         /* Radiosity parameters */
  81. Scene RadScene;            /* Scene to do radiosity on */
  82.  
  83. /**********************************************************************/
  84. void Read_Prim_Mesh();
  85. void Read_Mesh();
  86. void Read_Polygon();
  87. void Read_MToW();
  88. void Read_Surface_Properties();
  89. void GetMeshFromFile();
  90. int Read_Objects();
  91. void Read_Scene();
  92. void Print_InitialStats();
  93.  
  94. /*====================================================================*/
  95. /* Polygon setup  routines */
  96. /*====================================================================*/
  97. /**********************************************************************/
  98. /* Get d paramater of plane for a polgyon */
  99. /**********************************************************************/
  100. double Poly_PlaneD(poly_normal, poly_point)
  101.      Vector poly_normal, poly_point;
  102. {
  103.   return(-dot(&poly_normal, &poly_point));
  104. }
  105.  
  106. /**********************************************************************/
  107. /* Get area of a n-sided polygon using Stoke's Theorem */
  108. /**********************************************************************/
  109. double Poly_Area(v, norm, num_vert)
  110.      Vector v[MAX_PATCH_VTX];
  111.      Vector norm;
  112.      int num_vert;
  113. {
  114.   double area;
  115.   Vector v_cross_v1;
  116.   int i;
  117.   double sum_v;
  118.  
  119.   sum_v = 0.0;
  120.   for (i=0;i<num_vert;i++) {
  121.     v_cross_v1 = cross(&v[i],&v[(i+1) % num_vert]);
  122.     sum_v += dot(&norm, &v_cross_v1);
  123.   }
  124.   area = 0.5 * _ABS(sum_v);
  125.   if (area <= DAMN_SMALL)
  126.     printf("Hey the area is really small.\n");
  127.   if (area == 0.0) {
  128.     printf("Hey the area is too small.\n");
  129.     exit(1);
  130.   }
  131.   return area;
  132. }
  133.  
  134. /**********************************************************************/
  135. /* Find U, V, W planes formed by edges of quad or triangle            */
  136. /**********************************************************************/
  137. void Poly_UVW(pptr)
  138.      Polygon *pptr;
  139. {
  140.   int i;
  141.   Vector u,v,w;
  142.   Vector corner[MAX_PATCH_VTX];
  143.   polyUVW *uvw;
  144.  
  145.   uvw = (polyUVW *) malloc(sizeof(polyUVW));
  146.  
  147.   for (i=0;i<pptr->numVert;i++)
  148.     corner[i] = pptr->vert[i]->pos;
  149.  
  150.   if (pptr->class == PATCH) {
  151.     u = *vsub(&corner[1], &corner[0]);
  152.     uvw->Lu = vlen(&u);
  153.     norm(&u);
  154.     uvw->Nu = cross(&pptr->normal[0], &u);
  155.     uvw->du = Poly_PlaneD(uvw->Nu, corner[1]);
  156.     
  157.     v = *vsub(&corner[3], &corner[0]);
  158.     uvw->Lv = vlen(&v);
  159.     norm(&v);
  160.     uvw->Nv = cross(&v, &pptr->normal[0]);
  161.     uvw->dv = Poly_PlaneD(uvw->Nv, corner[3]);
  162.  
  163.   } else if (pptr->class == TRIANGLE) {
  164.     u = *vsub(&corner[1], &corner[0]);
  165.     uvw->Lu = vlen(&u);
  166.     norm(&u);
  167.     uvw->Nu = cross(&pptr->normal[0], &u);
  168.     uvw->du = Poly_PlaneD(uvw->Nu, corner[1]);
  169.  
  170.     v = *vsub(&corner[2], &corner[1]);
  171.     uvw->Lv = vlen(&v);
  172.     norm(&v);
  173.     uvw->Nv = cross(&pptr->normal[0], &v);
  174.     uvw->dv = Poly_PlaneD(uvw->Nv, corner[2]);
  175.  
  176.     w = *vsub(&corner[0], &corner[2]);
  177.     uvw->Lw = vlen(&w);
  178.     norm(&w);
  179.     uvw->Nw = cross(&pptr->normal[0], &w);
  180.     uvw->dw = Poly_PlaneD(uvw->Nw, corner[0]);
  181.  
  182.   } else {
  183.     fprintf(stderr, "Polygon type not supported. Can't calculate UVW.\n");
  184.     exit(1);
  185.   }
  186.   pptr->uvw = uvw;
  187. }
  188.  
  189.  
  190. /*====================================================================*/
  191. /* Scene reading routines */
  192. /*====================================================================*/
  193.  
  194. /**********************************************************************/
  195. /* Initialize size of world */
  196. /**********************************************************************/
  197. void Init_WorldSize(rlog)
  198.      RadParams *rlog;
  199. {
  200.   rlog->worldbox.min.x = VERY_LARGE / 2.0;
  201.   rlog->worldbox.min.y = VERY_LARGE / 2.0;
  202.   rlog->worldbox.min.z = VERY_LARGE / 2.0;
  203.   rlog->worldbox.max.x = -VERY_LARGE / 2.0;
  204.   rlog->worldbox.max.y = -VERY_LARGE / 2.0;
  205.   rlog->worldbox.max.z = -VERY_LARGE / 2.0;
  206.   rlog->worldSize = VERY_LARGE / 2.0;
  207. }
  208.  
  209. /**********************************************************************/
  210. /* Find minumum bounding box size for the world */
  211. /**********************************************************************/
  212. void Update_WorldSize(pt)
  213.      Vector pt;
  214. {
  215.   if (pt.x > ReadLog.worldbox.max.x)  ReadLog.worldbox.max.x = pt.x;
  216.   if (pt.y > ReadLog.worldbox.max.y)  ReadLog.worldbox.max.y = pt.y;
  217.   if (pt.z > ReadLog.worldbox.max.z)  ReadLog.worldbox.max.z = pt.z;
  218.  
  219.   if (pt.x < ReadLog.worldbox.min.x)  ReadLog.worldbox.min.x = pt.x;
  220.   if (pt.y < ReadLog.worldbox.min.y)  ReadLog.worldbox.min.y = pt.y;
  221.   if (pt.z < ReadLog.worldbox.min.z)  ReadLog.worldbox.min.z = pt.z;
  222. }
  223.  
  224. /**********************************************************************/
  225. /* Make bounding sphere and bounding box of world */
  226. /**********************************************************************/
  227. void BoxWorld(rlog)
  228.      RadParams *rlog;
  229. {
  230.   if (rlog->worldbox.min.x > rlog->worldbox.max.x) {
  231.     printf("Oh oh. the world min is greater than the max!\n");
  232.     exit(1);
  233.   }
  234.   rlog->worldbox.min.x -= ENLARGE_WORLD;
  235.   rlog->worldbox.min.y -= ENLARGE_WORLD;
  236.   rlog->worldbox.min.z -= ENLARGE_WORLD;
  237.   rlog->worldbox.max.x += ENLARGE_WORLD;
  238.   rlog->worldbox.max.y += ENLARGE_WORLD;
  239.   rlog->worldbox.max.z += ENLARGE_WORLD;
  240.  
  241.   rlog->worldSize = 0.5 * (vdist(&(rlog->worldbox.max), 
  242.                  &(rlog->worldbox.min)) + 0.5);
  243. }
  244.  
  245. /**********************************************************************/
  246. /* Make bounding sphere and bounding box of world */
  247. /**********************************************************************/
  248. void Enlarge_BoxSize(box)
  249.      BoundingBoxType *box;
  250. {
  251.   box->min.x -= ENLARGE_BOX;
  252.   box->min.y -= ENLARGE_BOX;
  253.   box->min.z -= ENLARGE_BOX;
  254.   box->max.x += ENLARGE_BOX;
  255.   box->max.y += ENLARGE_BOX;
  256.   box->max.z += ENLARGE_BOX;
  257. }
  258.  
  259. /**********************************************************************/
  260. /**********************************************************************/
  261. void Presub_Polygon(pptr, level)
  262.      Polygon *pptr;
  263.      int level;
  264. {
  265.   int i;
  266.  
  267.   /* printf("At level %d\n", level); */
  268.   if (level <= 0) return;
  269.   else {
  270.     Subdivide_Polygon(pptr);
  271.     level--;
  272.     for (i=0;i<MAX_PATCH_CHILDREN;i++) 
  273.       Presub_Polygon(pptr->child[i], level);
  274.   }
  275. }
  276.  
  277. /**********************************************************************/
  278. /* Read in polygon info */
  279. /**********************************************************************/
  280. void Read_Polygon(meshf, pptr, mptr, optr, origB)
  281.      FILE *meshf;
  282.      Polygon *pptr;
  283.      Mesh *mptr;
  284.      Objectt *optr;
  285.      Spectra origB;
  286. {
  287.   int i,j;
  288.   float tmpf[4];
  289.   char *tmp = "                    ";
  290.   Vector va[MAX_PATCH_VTX];
  291.   Vector v;
  292.  
  293.   /* Read in name and number of normals for the patch */
  294.   fscanf(meshf,"%s %d {",tmp , &(pptr->numVert));
  295.   pptr->id = ReadLog.totpoly++;
  296.   pptr->next = pptr+1;
  297.   if (Option.debug) printf("  Patch %s %d {", tmp, pptr->numVert);
  298.   
  299.   /* Set id, type, no children, tree level, mesh poly belongs to,
  300.    and poly, this poly belongs to */
  301.   if (pptr->numVert == 4) {
  302.     pptr->name = PATCH_ID;
  303.     pptr->class = PATCH;
  304.   } else if (pptr->numVert == 3) {
  305.     pptr->name = TRI_ID;
  306.     pptr->class = TRIANGLE;
  307.   } else {
  308.     fprintf(stderr, "Sorry, only quadtralaterals and triangles allowed\n");
  309.     exit(1);
  310.   }
  311.   for(i=0;i<MAX_PATCH_CHILDREN;i++)
  312.     pptr->child[i] = 0;               /* No children yet */
  313.   pptr->level = 0; pptr->Pfather = 0; /* is root of quad-tri tree */
  314.   pptr->Mfather = mptr;               /* mesh poly belongs to */
  315.   pptr->Links = (PolyList *)0;        /* No form factor links */
  316.   pptr->polyhead.front = pptr->polyhead.back = pptr->Links;
  317.   pptr->polyhead.num_polys = 0;
  318.     
  319.   /* Set total and unshot radiosity values for patch, and vertices */
  320.   for(i=0;i<MAX_SPECTRA_SAMPLES;i++) {
  321.     pptr->unshot_B.samples[i] = pptr->B.samples[i] = origB.samples[i];
  322.     for (j=0;j<pptr->numVert;j++)
  323.       pptr->vtx_B[j].samples[i] = origB.samples[i];
  324.   }
  325.   
  326.   /* Read normals of patch */
  327.   for (i=0;i<(pptr->numVert);i++) {
  328.     fscanf(meshf, " { %g %g %g }", &tmpf[0], &tmpf[1], &tmpf[2]);
  329.     pptr->normal[i].x = tmpf[0];
  330.     pptr->normal[i].y = tmpf[1];
  331.     pptr->normal[i].z = tmpf[2];
  332.     norm(&(pptr->normal[i]));
  333.  
  334.     /* Rotate normals if needed into world space */
  335.     if (same_matrix3x3(optr->MToW, Identity) == 0) {
  336.       pptr->normal[i] = vrotate(pptr->normal[i], optr->MToW);
  337.       norm(&(pptr->normal[i]));
  338.     }
  339.     
  340.     if (Option.debug)
  341.       printf(" { %g %g %g }", (pptr->normal[i].x),
  342.          (pptr->normal[i].y),(pptr->normal[i].z));
  343.   }
  344.   fscanf(meshf," }\n"); /* End normal read */
  345.   if (Option.debug) printf(" }\n");
  346.  
  347.   /* Read in size = number of vertices of patch */
  348.   fscanf(meshf, "Patch %s %d {", tmp, &(pptr->numVert));
  349.   if (Option.debug) printf("  Patch %s %d {", tmp, pptr->numVert);
  350.  
  351.   /* Read vertices of patch */
  352.   for (i=0;i<(pptr->numVert);i++) {
  353.     fscanf(meshf, " { %g %g %g }", &tmpf[0], &tmpf[1], &tmpf[2]);
  354.     v.x = tmpf[0]; 
  355.     v.y = tmpf[1]; 
  356.     v.z = tmpf[2];
  357.  
  358.     /* Transform vertex if needed into world space */
  359.     if (same_matrix(optr->MToW, Identity) == 0)
  360.       v = vtransform(v, optr->MToW);
  361.     if (Option.debug) printf(" {%g %g %g}", v.x, v.y, v.z);
  362.     va[i] = v;
  363.  
  364.     /* Update size of the world, and size of bounding box for mesh */
  365.     Update_WorldSize(v);
  366.     if (optr->num_meshes != -1)       /* Is not a primitive */
  367.       Update_BoxSize(v,optr->box);
  368.     if (optr->primid == MESH) 
  369.       Update_BoxSize(v,mptr->box);
  370.  
  371.     /* Form adjacency links between vertices and polygon */
  372.     if (vtree == 0) { /* Empty vertex tree */
  373.       pptr->vert[i] = Vertex_Create(v,pptr);
  374.       vtree = VTree_NodeCreate(pptr->vert[i],0); /* No father, is root */
  375.     } else {
  376.       VTree_NodeFind(v,vtree,pptr,i);
  377.     }
  378.   
  379.   }
  380.   fscanf(meshf," }\n"); /* End polygon vertex read */
  381.   if (Option.debug) printf(" }\n");
  382.  
  383.   /* Calculate area and d of plane where poly resides */  
  384.   pptr->d = Poly_PlaneD(pptr->normal[1], va[1]);
  385.   pptr->area = Poly_Area(va, pptr->normal[0], pptr->numVert);
  386.  
  387.   /* Calculate u,v,w planes of edges of poly */
  388.   Poly_UVW(pptr);
  389.   pptr->changingNormal = 0;
  390.  
  391.   /* Calculate total energy and total area in scene */
  392.   ReadLog.totalArea += pptr->area;
  393.   for(i=0;i<MAX_SPECTRA_SAMPLES;i++)
  394.     ReadLog.totalEnergy += origB.samples[i] * pptr->area;
  395.  
  396.   /* Pre-subdivide if specified */
  397.   if (premesh == 1) 
  398.     Subdivide_Polygon(pptr);
  399.   else if (premesh > 1) 
  400.     Presub_Polygon(pptr, premesh);
  401. }
  402.  
  403. /**********************************************************************/
  404. /* Read mesh info */
  405. /**********************************************************************/
  406. void Read_Mesh(meshf, optr)
  407.      FILE *meshf;
  408.      Objectt *optr;
  409. {
  410.   Mesh *mptr;
  411.   Polygon *pptr;
  412.   char *tmp = "                    ";
  413.  
  414.   if (Option.debug) printf("  NumMeshes %d\n", optr->num_meshes);
  415.   mptr = optr->meshes
  416.     = (Mesh *)malloc ((optr->num_meshes) *sizeof(Mesh));
  417.   ReadLog.meshcount = 0;
  418.  
  419.   /* Read in mesh information from current input file */
  420.   while ((fscanf(meshf,"    Mesh ") != -1) && 
  421.      (ReadLog.meshcount < optr->num_meshes)) {
  422.  
  423.     /* Allocate space for polygons in mesh */
  424.     fscanf(meshf, "%s %d {\n", tmp, &(mptr->num_polys));
  425.     mptr->id = ReadLog.totmesh++;
  426.     mptr->name = MESH_ID;
  427.     mptr->Ofather = optr;
  428.     pptr = mptr->polys
  429.       = (Polygon *)malloc ((mptr->num_polys) *sizeof(Polygon));
  430.  
  431.     /* Allocate space for mesh bounding box if object is 
  432.        a polygonal mesh */
  433.     if (optr->primid == MESH) {
  434.       mptr->box = (BoundingBoxType *) malloc(sizeof(BoundingBoxType));
  435.       BoxInit(mptr->box);
  436.     } else 
  437.       mptr->box = (BoundingBoxType *)0;
  438.  
  439.     if (Option.debug) printf("  Mesh %s %d {\n", tmp, mptr->num_polys);
  440.     
  441.     /* Read in polygon information for mesh */
  442.     ReadLog.polycount = 0;
  443.     while ((fscanf(meshf,"    Patch ") != -1) && 
  444.        (ReadLog.polycount < mptr->num_polys)) {
  445.       
  446.       Read_Polygon(meshf,pptr,mptr,optr,optr->surface->rad.E);
  447.       pptr++;
  448.       ReadLog.polycount++;
  449.     }
  450.     fscanf(meshf,"    }\n"); /* End mesh read */
  451.  
  452.     mptr++;
  453.     ReadLog.meshcount++;
  454.   }
  455. }
  456.  
  457. /**********************************************************************/
  458. /* Read object to world space matrix, and create inverse matrix */
  459. /**********************************************************************/
  460. void Read_MToW(meshf, optr)
  461.      FILE *meshf;
  462.      Objectt *optr;
  463. {
  464.   int i,j;
  465.  
  466.   /* Read in object to world matrix, and set world-object matrix */
  467.   fscanf(meshf,"OWMatrix %s { ", tmp);
  468.   copy_matrix(Identity, optr->MToW);
  469.   for (i=0; i<4; i++) for (j=0; j<3; j++) {
  470.     fscanf(meshf,"%g ", &tmpf[0]);
  471.     optr->MToW[i][j] = tmpf[0];
  472.   }
  473.   invert_matrix(optr->MToW,optr->WToM);
  474.   fscanf(meshf,"}\n"); /* End read matrix */
  475.           
  476.   if (Option.debug) {
  477.     printf("  OWMatrix %s {\n", tmp);
  478.     for(i=0;i<4;i++) {
  479.       printf("\t");
  480.       for(j=0;j<4;j++) printf("%g ", optr->MToW[i][j]);
  481.       printf("\n");
  482.     }
  483.   }
  484. }
  485.  
  486. /**********************************************************************/
  487. /* Allocate space and read in object surface properties */
  488. /**********************************************************************/
  489. void Read_Surface_Properties(meshf, optr)
  490.      FILE *meshf;
  491.      Objectt *optr;
  492.   SurfaceProp *sptr;
  493.   static int surfprop_id = 0;
  494.  
  495.   /* Allocate space for surface properties */
  496.   sptr = optr->surface = (SurfaceProp *)malloc(sizeof(SurfaceProp));    
  497.    
  498.   fscanf(meshf,
  499.      "    Prop %s { E{ %g %g %g } p{ %g %g %g } Kd{ %g } Ks{ %g } }\n",
  500.      tmp, &tmpf[0], &tmpf[1], &tmpf[2], &tmpf[3], &tmpf[4], &tmpf[5],
  501.      &tmpf[6], &tmpf[7]);
  502.   sptr->id = surfprop_id++;
  503.   sptr->name = tmp;
  504.   sptr->rad.E.samples[0] = tmpf[0];    /* Emittance */
  505.   sptr->rad.E.samples[1] = tmpf[1]; 
  506.   sptr->rad.E.samples[2] = tmpf[2];
  507.   sptr->shade.p.samples[0] = tmpf[3];  /* Reflectance */
  508.   sptr->shade.p.samples[1] = tmpf[4];
  509.   sptr->shade.p.samples[2] = tmpf[5];
  510.   sptr->shade.Kd.samples[0] = tmpf[6]; /* Diffuse & specular coefficients */
  511.   sptr->shade.Ks.samples[0] = tmpf[7];
  512.   sptr->rad.B.samples[0] = 0.0;        /* Radiance */
  513.   sptr->rad.B.samples[1] = 0.0;
  514.   sptr->rad.B.samples[2] = 0.0;
  515.  
  516.   if (Option.debug) 
  517.     printf("  Prop %s { E{ %g %g %g } p{ %g %g %g } Kd{ %g } Ks{ %g } }\n",
  518.        tmp, sptr->rad.E.samples[0],
  519.        sptr->rad.E.samples[1], sptr->rad.E.samples[2],
  520.        sptr->shade.p.samples[0], sptr->shade.p.samples[1], 
  521.        sptr->shade.p.samples[2], 
  522.        sptr->shade.Kd.samples[0], sptr->shade.Ks.samples[0]);
  523. }
  524.  
  525. /**********************************************************************/
  526. /* Read in mesh from primitive mesh file */
  527. /**********************************************************************/
  528. void Read_Prim_Mesh(filename, optr)
  529.      char *filename;
  530.      Objectt *optr;
  531. {
  532.   if (!(pmesh = fopen(filename, "r"))) {
  533.     fprintf(stderr,"%s: cannot read object file %s\n", ProgName, filename);
  534.     exit(1);
  535.   }
  536.  
  537.   fscanf(pmesh, "NumMeshes %d\n", &(optr->num_meshes));
  538.   ReadLog.polycount = 0;
  539.   Read_Mesh(pmesh, optr);
  540.   fclose(pmesh);
  541. }
  542.  
  543. /**********************************************************************/
  544. /* Read in scene from a input file */
  545. /**********************************************************************/
  546. void GetMeshFromFile(objtype, optr)
  547.      char *objtype;
  548.      Objectt *optr;
  549. {
  550.   BoundingBoxType obox;
  551.  
  552.   optr->primtype = objtype;
  553.  
  554.   /* Check if normals facing in or out */
  555.   if (optr->num_meshes == -2) 
  556.     optr->in_facingprim = TRUE;
  557.   else
  558.     optr->in_facingprim = FALSE;
  559.  
  560.   if (strcmp(objtype,"cone") == 0) {
  561.     obox = BoxCone();
  562.     optr->primid = CONE;
  563.     if (optr->num_meshes == -2) {
  564.       if (ReadLog.log) printf("\t*** cone(in) reading...\n");
  565.       Read_Prim_Mesh(iconefilename, optr);
  566.     } else {
  567.       if (ReadLog.log) printf("\t*** cone(out) reading...\n");
  568.       Read_Prim_Mesh(conefilename, optr);
  569.     }
  570.   } else if (strcmp(objtype,"cube") == 0) {
  571.     obox = BoxCube();
  572.     optr->primid = CUBE;
  573.     if (optr->num_meshes == -2) {
  574.       if (ReadLog.log) printf("\t*** cube(in) reading...\n");
  575.       Read_Prim_Mesh(icubefilename, optr);
  576.     } else {
  577.       if (ReadLog.log) printf("\t*** cube(out) reading...\n");
  578.       Read_Prim_Mesh(cubefilename, optr);
  579.     }
  580.   } else if (strcmp(objtype,"cylinder") == 0) {
  581.     obox = BoxCylinder();
  582.     optr->primid = CYLINDER;
  583.     if (optr->num_meshes == -2) {
  584.       if (ReadLog.log) printf("\t*** cylinder(in) reading...\n");
  585.       Read_Prim_Mesh(icylfilename, optr);
  586.     } else {
  587.       if (ReadLog.log) printf("\t*** cylinder(out) reading...\n");
  588.       Read_Prim_Mesh(cylfilename, optr);
  589.     }
  590.   } else if (strcmp(objtype,"sphere") == 0) {
  591.     obox = BoxSphere();
  592.     optr->primid = SPHERE;
  593.     if (optr->num_meshes == -2) {
  594.       if (ReadLog.log) printf("\t*** sphere(in) reading...\n");
  595.       Read_Prim_Mesh(isphfilename, optr);
  596.     } else {
  597.       if (ReadLog.log) printf("\t*** sphere(out) reading...\n");
  598.       Read_Prim_Mesh(sphfilename, optr);
  599.     }
  600.   } else {
  601.     printf("There's something wrong, primitive is invalid\n");
  602.     exit(0);
  603.   }
  604.   /* optr->num_meshes = -1; */
  605.  
  606.   /* Get transformed bounding box for object if tranformation 
  607.      not Identity */
  608.   if (same_matrix3x3(optr->MToW, Identity) == 0)
  609.     Bounds_Transform(optr->MToW, obox, optr->box);
  610.   Option.debug = 0;
  611. }
  612.  
  613. char *objmatch[5] = 
  614.   "precone", "precube", "precylinder", "premesh", "presphere" 
  615. };
  616. char *objreal[5] = 
  617.   "cone", "cube", "cylinder", "mesh", "sphere" 
  618.   };
  619. /**********************************************************************/
  620. /* Search string a for b, and return first number found               */
  621. /**********************************************************************/
  622. int Check_premesh(a, realtype)
  623.      char *a, **realtype;
  624. {
  625.   int match = 0;          /* Match found */
  626.   char level[2];          /* level to subdivide to */
  627.   int i;
  628.  
  629.   i=0;
  630.   while (i<5 && !match)   /* Scan for object type, return type */
  631.     if (strstr(a,objmatch[i])) {
  632.       match = 1;
  633.       *realtype = objreal[i];
  634.     }
  635.     else i++;
  636.  
  637.   if (match)              /* Scan for number of levels to mesh to */
  638.     for (i=0;i<9;i++) {
  639.       sprintf(level, "%d", i+1);
  640.       if (strstr(a, level))
  641.     match = i+1;
  642.     }
  643.   return(match);
  644. }
  645.  
  646. /**********************************************************************/
  647. /* Read in objects from file */
  648. /**********************************************************************/
  649. int Read_Objects(filename, obj)
  650.      char *filename;
  651.      Objectt **obj;     
  652. {
  653.   int nobjs = 0;                  /* Number of objects to read */
  654.   Objectt *optr;
  655.  
  656.   if (!(meshf = fopen(filename, "r"))) {
  657.     fprintf(stderr,"%s: cannot read object file %s\n", ProgName, filename);
  658.     exit(1);
  659.   }
  660.  
  661.   /* Find out # of objects and allocate space */
  662.   fscanf(meshf,"Number objects %d\n", &nobjs);
  663.   if (Option.debug) printf("Number objects %d\n", nobjs);
  664.   optr = *obj = (Objectt *)malloc (nobjs *sizeof(Objectt));
  665.  
  666.   /* Scan for objects (id, object type) */
  667.   ReadLog.objcount = 0;
  668.   while ((fscanf(meshf,"Object") != -1) && (ReadLog.objcount < nobjs)) {
  669.  
  670.     /* Set id, name, and primitive type */
  671.     fscanf(meshf, "%s %s {\n", tmp, tmp2);
  672.     optr->id = ReadLog.objcount;
  673.     optr->rayID = -1;
  674.     optr->name = "object"; 
  675.     optr->primtype = tmp2;
  676.  
  677.     if (premesh = Check_premesh(tmp2,&optr->primtype))
  678.       printf("\t    Tesselating %s (%d) to level %d\n", 
  679.          optr->primtype, optr->id, premesh);
  680.  
  681.     if (Option.debug)
  682.       printf("Object%d %s %s {\n", optr->id, optr->name, optr->primtype);
  683.  
  684.     /* Allocate space for object bounding volume */
  685.     optr->box = (BoundingBoxType *) malloc(sizeof(BoundingBoxType));
  686.  
  687.     /* Read model to world matrix */
  688.     Read_MToW(meshf, optr);
  689.  
  690.     /* Read surface properties */
  691.     Read_Surface_Properties(meshf, optr);
  692.       
  693.     /* Find out number of meshes in object */
  694.     fscanf(meshf, "    NumMeshes %d\n", &(optr->num_meshes));
  695.  
  696.     if ((optr->num_meshes) == -1 || (optr->num_meshes) == -2) {
  697.       /* Read in mesh info from primitive-mesh input files */
  698.       /* depending on type of object */
  699.       GetMeshFromFile(optr->primtype,optr); 
  700.  
  701.     } else {
  702.       /* Reading in mesh info from current input file */
  703.       if (ReadLog.log) printf("\t*** mesh reading...\n");
  704.       optr->primid = MESH;
  705.       BoxInit(optr->box);
  706.       Read_Mesh(meshf, optr);
  707.     }
  708.     fscanf(meshf,"}\n"); /* End object read */
  709.     if (Option.debug) printf("}\n");
  710.  
  711.     /* Enlarge box around object just a bit ? */
  712.     /* Enlarge_BoxSize(optr->box); */
  713.     
  714.     optr++;
  715.     ReadLog.objcount++;
  716.   }
  717.  
  718.   ReadLog.totalEnergyLeft = ReadLog.totalEnergy;
  719.   fclose(meshf);
  720.   return(ReadLog.objcount);
  721. }
  722.  
  723. /**********************************************************************/
  724. /* Read in textures from file */
  725. /**********************************************************************/
  726. int Read_Textures(filename, tex)
  727.      char *filename;
  728.      TextureProp **tex;     
  729. {
  730.   if (!(textf = fopen(filename, "r"))) {
  731.     fprintf(stderr,"%s: cannot read texture file %s\n", ProgName, filename);
  732.     exit(1);
  733.   }
  734.   printf("Not implemented yet...sorry no textures\n");
  735.   return 0;
  736. }
  737.  
  738. /**********************************************************************/
  739. /* Print element / receiver list */
  740. /**********************************************************************/
  741. void Print_Elements(elist,elist_size)
  742.      Elist *elist;
  743.      int elist_size;
  744. {
  745.   int i;
  746.   Elist *elptr;
  747.  
  748.   elptr = elist;
  749.   for(i=0;i<elist_size;i++,elptr=elptr->next)
  750.     printf("\tElement %s%d, ff %g, is %sa receiver\n",
  751.        elptr->element->name, elptr->element->id,
  752.        elptr->ff, (elptr->is_receiver == 1 ? "" : "not "));
  753. }
  754.  
  755. /**********************************************************************/
  756. /* Print program options, and statistics */
  757. /**********************************************************************/
  758. void Print_InitialStats(rlog,fp)
  759.      RadParams rlog;
  760.      FILE *fp;
  761. {
  762.   if (rlog.log) {
  763.     fprintf(fp,"\n\t*** Scene statistics ***\n");
  764.     fprintf(fp,"\tTotal objects read: %d\n", rlog.objcount);
  765.     fprintf(fp,"\tTotal meshes read: %d\n", rlog.totmesh);
  766.     fprintf(fp,"\tTotal polygons read: %d\n", rlog.totpoly);
  767.     fprintf(fp,"\tTotal vertices read to octree: %d\n", vtree_size);
  768.     fprintf(fp,"\tTotal textures read: %d\n", rlog.num_textures);
  769.     fprintf(fp,"\n");
  770.     /* if (ReadLog.num_elements > 0) {
  771.        fprintf(fp,"\tTotal elements read: %d\n", rlog.num_elements);
  772.        Print_Elements(rlog.elements, rlog.num_elements);
  773.        fprintf(fp,"\tTotal receivers: %d\n", rlog.num_receivers);
  774.        } */
  775.     fprintf(fp,"\tStopping threshold: %g and iterations: %d\n", rlog.threshold,
  776.        rlog.max_iterations);
  777.     fprintf(fp,"\tIntensity scale for display: %g\n", rlog.intensityScale);
  778.     /* if (Option.ambient)
  779.        fprintf(fp,"\tInitial ambient term: (%g %g %g)\n", 
  780.        rlog.ambient_term.samples[0], rlog.ambient_term.samples[1],
  781.        rlog.ambient_term.samples[2]);
  782.        */
  783.     fprintf(fp,"\tThe worlds radius is: %g\n", rlog.worldSize);
  784.     fprintf(fp,"\t\twith min-point %g,%g,%g\n\t\tand max-point %g,%g,%g\n",
  785.        rlog.worldbox.min.x, rlog.worldbox.min.y, rlog.worldbox.min.z, 
  786.        rlog.worldbox.max.x, rlog.worldbox.max.y, rlog.worldbox.max.z);
  787.     fprintf(fp,"\t\thas a total energy of: %g\n", rlog.totalEnergy);
  788.     fprintf(fp,"\t\tand has a total area of: %g\n", rlog.totalArea);
  789.  
  790.     ff_print_FF_Options(FF_Options);
  791.     if (Option.ff_raytrace == 0) {
  792.       fprintf(fp,"\tUsing hemicube visibility testing, with\n");
  793.       fprintf(fp,"\ttop resolution of %d\n", rlog.hemicubeRes);
  794.     } else {
  795.       if (FF_Options.quadtri_ray) 
  796.     fprintf(fp,"\tUsing Ray-QuadTri intersection test.\n");
  797.       else
  798.     fprintf(fp,"\tUsing Ray-General Polygon intersection test.\n");
  799.       if (Option.grid)
  800.     fprintf(fp,"\tUsing hierarchical bounding volumes\n");
  801.       if (FF_Options.shaft_cull) 
  802.     fprintf(fp,"\tUsing source/receiver shaft culling\n");
  803.       else {
  804.     if (FF_Options.src_rec_cull) 
  805.       fprintf(fp,"\tUsing source and receiver plane culling.\n");
  806.     else
  807.       fprintf(fp,"\tUsing source plane culling.\n");
  808.       }
  809.     }
  810.     fprintf(fp,"\n");
  811.   }
  812. }
  813.  
  814. /**********************************************************************/
  815. /* Read in the scene (s) from file */
  816. /**********************************************************************/
  817. void Read_Scene(s)
  818.      Scene *s;
  819. {
  820.   printf("\n\t*** Reading scene from %s ***\n",Option.meshfilename);
  821.  
  822.   /* Initialize size of the world */
  823.   Init_WorldSize(&ReadLog);
  824.  
  825.   /* Create vertex octree */
  826.   /* vtree = VTree_Create(ReadLog); */
  827.  
  828.   /* Read in objects and textures */
  829.   s->num_objects = Read_Objects(Option.meshfilename, &(s->objects));
  830.   /*  s->num_textures = Read_Textures(Option.textfilename, &(s->textures)); */
  831.  
  832.   /* Read in PR view */
  833.   printf("\n\t*** Reading view from %s ***\n", Option.viewfilename);
  834.   Read_View(Option.viewfilename,&(ReadLog.displayView));
  835.  
  836.   /* Calculate minimum  world size */
  837.   BoxWorld(&ReadLog);
  838.  
  839.   /* Set minimum element area */
  840.   FF_Options.min_element_area = (MIN_ELEMENT_PERC * ReadLog.totalArea / 
  841.                  (double) ReadLog.totpoly);
  842. }
  843.  
  844. /**********************************************************************/
  845. /* Read in a view */
  846. /**********************************************************************/
  847. void Read_View(filename,c)
  848.      char *filename;
  849.      Camera *c;
  850. {
  851.   float t[3];
  852.   int t1, t2;
  853.  
  854.   if (!(viewf = fopen(filename, "r"))) {
  855.     fprintf(stderr,"\t%s: cannot read view file %s\n", ProgName, filename);
  856.     fprintf(stderr,"\tSetting to default viewing parameters\n");
  857.     c->lookfrom.x = ReadLog.worldbox.max.x - 2.*ENLARGE_WORLD;
  858.     c->lookfrom.y = ReadLog.worldbox.max.y - 2.*ENLARGE_WORLD;
  859.     c->lookfrom.z = ReadLog.worldbox.max.z - 2.*ENLARGE_WORLD;
  860.     c->lookat.x = (ReadLog.worldbox.max.x - ReadLog.worldbox.min.x ) / 2.0;
  861.     c->lookat.y = (ReadLog.worldbox.max.y - ReadLog.worldbox.min.y ) / 2.0;
  862.     c->lookat.z = (ReadLog.worldbox.max.z - ReadLog.worldbox.min.z ) / 2.0;
  863.     c->lookup.x = 0.;    c->lookup.y = 1.;       c->lookup.z = 0.;
  864.     c->fovx = 60;   c->fovy = 60;
  865.     c->near = 0.001; c->far = ReadLog.worldSize;
  866.     c->xRes = 256; c->yRes = 256;
  867.     c->bank = 0.0;
  868.  
  869.   } else {
  870.     fscanf(viewf,"Camera {\n");
  871.  
  872.     fscanf(viewf,"lookfrom %g %g %g\n", &t[0], &t[1], &t[2]);
  873.     c->lookfrom.x = t[0];
  874.     c->lookfrom.y = t[1];
  875.     c->lookfrom.z = t[2];
  876.     
  877.     fscanf(viewf,"lookat %g %g %g\n", &t[0], &t[1], &t[2]);
  878.     c->lookat.x = t[0];
  879.     c->lookat.y = t[1];
  880.     c->lookat.z = t[2];
  881.     
  882.     fscanf(viewf,"lookup %g %g %g\n", &t[0], &t[1], &t[2]);
  883.     c->lookup.x = t[0];
  884.     c->lookup.y = t[1];
  885.     c->lookup.z = t[2];
  886.     
  887.     fscanf(viewf,"fovx %d fovy %d near %g far %g\n", &t1, &t2, &t[0], &t[1]);
  888.     c->fovx = t1;   c->fovy = t2;
  889.     c->near = t[0]; c->far = t[1];
  890.     fscanf(viewf,"xRes %d yRes %d\n", &t1, &t2);
  891.     c->xRes = t1; c->yRes = t2;
  892.     fscanf(viewf,"bank %g\n", &t[0]);
  893.     c->bank = t[0];
  894.     fscanf(viewf,"}");
  895.   }
  896.  
  897.   /* Allocate buffer for display purposes */
  898.   c->buffer = (unsigned  long *)
  899.     malloc(ReadLog.displayView.xRes * ReadLog.displayView.yRes *
  900.        sizeof(unsigned long));
  901. }
  902.  
  903. extern int p_count;
  904. /**********************************************************************/
  905. /* Main program... */
  906. /**********************************************************************/
  907. void main(argc, argv)
  908.      int argc;
  909.      char *argv[];
  910. {
  911.   int temp;
  912.   float prep_start, prep_end;
  913.   float tot_start, tot_end;
  914.   char *env_var = "                                                  ";
  915.  
  916.   /* Set up options */
  917.   SetOptions(argc, argv);
  918.   Init_Time();
  919.  
  920.   /* Open table log */
  921.   if ((env_var = getenv("PR_run")) != NULL) {
  922.     Option.tablelogstr = env_var;  
  923.     Option.tablelog = TRUE;
  924.     LogRlog(1,Option.meshfilename,Option.tablelogstr);
  925.   } else 
  926.     Option.tablelog = FALSE;
  927.  
  928.   /* Read the scene in */
  929.   temp = Option.debug; Option.debug = 0;  
  930.  
  931.   if (Option.statistics)
  932.     prep_start = Cpu_Time(&tstats.utime, &tstats.stime);
  933.  
  934.   Read_Scene(&RadScene);
  935.  
  936.   if (Option.statistics) {
  937.     prep_end = Cpu_Time(&tstats.utime, &tstats.stime);
  938.     tstats.prep_Model = (prep_end - prep_start);
  939.   }
  940.  
  941.   if (Option.statistics)
  942.     if (Option.device == PRINT) Print_InitialStats(ReadLog,stdout);
  943.     else Print_InitialStats(ReadLog,Option.StatFile);
  944.   if (Option.print_scene) print_Scene(&RadScene,Option.InLogFilename);
  945.   Option.debug = temp;
  946.  
  947.   /* Build hierarchical bounding volume tree for scene */
  948.   if (Option.grid) { 
  949.  
  950.     /* Build object HBV */
  951.     prep_start = Cpu_Time(&tstats.utime, &tstats.stime);
  952.  
  953.     BVH_Create_Hierarchy(&RadScene, &Scene_BVH);
  954.  
  955.     prep_end = Cpu_Time(&tstats.utime, &tstats.stime);
  956.     tstats.prep_oHBV = (prep_end - prep_start);
  957.     tstats.tot_time += tstats.prep_oHBV;
  958.  
  959.     prep_start = Cpu_Time(&tstats.utime, &tstats.stime);
  960.     
  961.     /* Build polygon HBV */
  962.     BVH_Create_PHierarchy(&Scene_BVH);
  963.     /* printf("\t%d Polygons added to tree.\n", p_count); */
  964.     Enlarge_Root();
  965.  
  966.     prep_end = Cpu_Time(&tstats.utime, &tstats.stime);
  967.     tstats.prep_pHBV = (prep_end - prep_start);
  968.     tstats.tot_time += tstats.prep_pHBV;
  969.  
  970.     if (Option.debug) {
  971.       printf("\t*** Hierarchical BV tree ***\n");
  972.       temp = Option.debug;
  973.       Option.debug = 0;
  974.       BVH_PrintBox(&Scene_BVH);
  975.       BVH_PrintHier(&Scene_BVH);
  976.       printf("\n");
  977.       Option.debug = temp;
  978.     }
  979.   }
  980.  
  981.   /* Run radiosity on the scene */
  982.   Init_Rad(&RadScene);
  983.   Do_Rad();
  984.  
  985.   /* Perform cleanup */
  986.   /* CleanUp_Rad(); */
  987.   if (Option.statistics)
  988.     if (Option.device == FILES)
  989.       LogStats(0);
  990.  
  991.   /* Log scene with radiosity calculated */
  992.   if (Option.print_scene) print_Scene(&RadScene, Option.OutLogFilename);
  993.  
  994.   /* Output polygonal scene to file */
  995.   if (Option.write_result) {
  996.     /*  Create_Initial_ReceiverList(&RadScene); */
  997.     Write_Rad(ReadLog, Option.OutSceneFilename,-1);
  998.   }
  999.  
  1000.   /* Close table log */
  1001.   if (Option.tablelog == TRUE)
  1002.     LogRlog(0,"","");
  1003. }
  1004.